package dilema_do_prisioneiro;

import java.awt.Color;
import java.awt.Dimension;
import java.util.ArrayList;
import java.util.List;
import javax.swing.JFrame;
import org.jfree.chart.ChartFactory;
import org.jfree.chart.ChartPanel;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.plot.PlotOrientation;
import org.jfree.chart.renderer.category.CategoryItemRenderer;
import org.jfree.data.category.CategoryDataset;
import org.jfree.data.category.DefaultCategoryDataset;

/**
 *
 * @author Guilherme
 */
public class Principal {

    private int numero_execucoes = 5;
    private int quant_geracoes = 400;
    private int tipo_individuos = 0;// 0 = um a um, 1 = um por meia população, 2 = 1 por populacao
    private int tipo_fitness = 0;// 0 = Individual, 1 = Grupo

    public Principal() {
        List<List<Double>> resultados_melhor = new ArrayList();
        List<List<Double>> resultados_media = new ArrayList();
        for (int a = 0; a < numero_execucoes; a++) {
            List<Double> melhor_por_geracao = new ArrayList();
            List<Double> media_por_geracao = new ArrayList();
            //
            DilemaPrisioneiro dp0 = new DilemaPrisioneiro(tipo_individuos, tipo_fitness);
            for (int i = 0; i < quant_geracoes; i++) {
                dp0.torneio();                
                //Salva Resultados da Geração
                melhor_por_geracao.add(dp0.getMaiorFitness());
                media_por_geracao.add(dp0.getMediaFitness());
                //
                dp0.cruzamento();
                dp0.mutacao();
                //dp0.imprimePopulacao(i);                
            }
            resultados_melhor.add(melhor_por_geracao);
            resultados_media.add(media_por_geracao);
        }
        this.plotarGrafico(resultados_melhor, "Melhor");
        this.plotarGrafico(resultados_media, "Média");
    }

    private void plotarGrafico(List<List<Double>> resultados, String label) {
        CategoryDataset ds = new DefaultCategoryDataset();
        for (int x = 0; x < resultados.size(); x++) {
            List<Double> resultados_por_geracao = resultados.get(x);
            for (int i = 0; i < resultados_por_geracao.size(); i++) {
                ((DefaultCategoryDataset) ds).addValue(resultados_por_geracao.get(i), label + x, "" + i);
            }
        }
        JFreeChart grafico = ChartFactory.createLineChart("Gráfico " + label + " por geração", "Geração", "Valor", ds, PlotOrientation.VERTICAL, true, true, false);
        JFrame frame = new JFrame("Gráfico de " + resultados.get(0).size() + " pontos");
        frame.add(new ChartPanel(grafico));
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setPreferredSize(new Dimension(910, 550));
        frame.pack();
        frame.setVisible(true);
        //Media dos Gráficos
        CategoryDataset ds2 = new DefaultCategoryDataset();
        for (int i = 0; i < resultados.get(0).size(); i++) {
            List<Double> resultado_por_execucao = new ArrayList();
            for (int j = 0; j < resultados.size(); j++) {
                resultado_por_execucao.add(resultados.get(j).get(i));
            }
            Double[] media_desvio = this.calcularMediaDesvio(resultado_por_execucao);
            ((DefaultCategoryDataset) ds2).addValue(media_desvio[0] + media_desvio[1], "Desvio Superior", "" + i);
            ((DefaultCategoryDataset) ds2).addValue(media_desvio[0], "Média Execucoes " + label, "" + i);
            ((DefaultCategoryDataset) ds2).addValue(media_desvio[0] - media_desvio[1], "Desvio Inferior", "" + i);
        }
        JFreeChart grafico2 = ChartFactory.createLineChart("Gráfico " + label + " por geração", "Geração", "Valor", ds2, PlotOrientation.VERTICAL, true, true, false);
        JFrame frame2 = new JFrame("Gráfico de " + resultados.get(0).size() + " pontos");
        CategoryItemRenderer renderer = grafico2.getCategoryPlot().getRenderer();
        renderer.setSeriesPaint(0, Color.RED);
        renderer.setSeriesPaint(1, Color.BLUE);
        renderer.setSeriesPaint(2, Color.RED);
        frame2.add(new ChartPanel(grafico2));
        frame2.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame2.setPreferredSize(new Dimension(910, 550));
        frame2.pack();
        frame2.setVisible(true);
    }

    private Double[] calcularMediaDesvio(List<Double> amostras) {
        double soma = 0.0, media, desvio;
        for (int i = 0; i < amostras.size(); i++) {
            soma += (amostras.get(i) != null) ? amostras.get(i) : 0.0;
        }
        media = soma / amostras.size();
        soma = 0.0;
        for (int i = 0; i < amostras.size(); i++) {
            soma += Math.pow(media - amostras.get(i), 2.0);
        }
        desvio = Math.sqrt(soma / (amostras.size() - 1));
        return new Double[]{media, desvio};
    }

    public static void main(String[] args) {
        new Principal();
    }

}
